package de.stefanocke.roo.wicket.templates;

import java.util.HashMap;
import java.util.Map;

import org.springframework.roo.model.JavaPackage;
import org.springframework.roo.project.ProjectOperations;

import de.stefanocke.roo.wicket.ApplicationService;
import de.stefanocke.roo.wicket.ValidationException;

public class Templates {
	private TemplateSupportService templateSupportService;
	private ApplicationService applicationService;
	private ProjectOperations projectOperations;
	private JavaPackage webPackage;
	private JavaPackage domainPackage;
	// private String moduleName; //TODO: the stereotypes might be in some other
	// module, especially the ones for the domain classes

	//TODO: Get rid of this list.
	private final IJavaTemplate[] templates = new IJavaTemplate[] {
			new WicketApplicationTemplate(), //
			new BasePageTemplate(), //
			new HomePageTemplate(), new EntityModelTemplate(), new DataProviderTemplate(),
			new ComponentFactoryTemplate(), new AnnotationUtilsTemplate(),
			new DetailsTemplate(), new TableTemplate(), new FormTemplate(),
			new FormFieldsTemplate(), /*  new DateTimeFieldTemplate(), new EnumSelectTemplate(), */
			new ListEditorTemplate(), new ILabeledTemplate(), new DecoratorFragmentTemplate(),
			new IdentifiableTemplate(),
			new VersionedTemplate() };

	private Map<Class<?>, IJavaTemplate> classToTemplate = new HashMap<Class<?>, IJavaTemplate>();
	private String focusedModule;

	public Templates(TemplateSupportService templateSupportService, ApplicationService applicationService,
			ProjectOperations projectOperations, String focusedModule, JavaPackage requestedWebPackage,
			JavaPackage requestedDomainPackage) {
		this.templateSupportService = templateSupportService;
		this.applicationService = applicationService;
		this.projectOperations = projectOperations;
		this.focusedModule = focusedModule;
		determineWebPackage(requestedWebPackage);
		determineDomainPackage(requestedDomainPackage);

		for (IJavaTemplate template : templates) {
			template.init(this);
			classToTemplate.put(template.getClass(), template);
		}
	}

	private void determineDomainPackage(JavaPackage requestedDomainPackage) {
		this.domainPackage = requestedDomainPackage;
		if (this.domainPackage == null) {
			this.domainPackage = new JavaPackage(projectOperations.getTopLevelPackage(focusedModule)
					.getFullyQualifiedPackageName() + ".domain");
		}

	}

	private void determineWebPackage(JavaPackage requestedWebPackage) {
		this.webPackage = this.applicationService.getWebPackage(focusedModule);
		if (webPackage != null && requestedWebPackage != null && !webPackage.equals(requestedWebPackage)) {
			throw new ValidationException("There is already a Wicket application class in package " + this.webPackage
					+ ". It is not allowed to specify a different webPackage in this case.");
		}
		if (this.webPackage == null) {
			this.webPackage = requestedWebPackage;
		}
		if (this.webPackage == null) {
			this.webPackage = new JavaPackage(projectOperations.getTopLevelPackage(focusedModule)
					.getFullyQualifiedPackageName() + ".web");
		}
	}

	public void createOrUpdateFiles(boolean forceUpdate) {
		for (IJavaTemplate template : templates) {
			template.createFiles(forceUpdate);
		}
	}

	public IJavaTemplate getTemplate(Class<? extends IJavaTemplate> clazz) {
		return classToTemplate.get(clazz);
	}

	public TemplateSupportService getTemplateSupportService() {
		return templateSupportService;
	}

	public ApplicationService getApplicationService() {
		return applicationService;
	}

	/**
	 * 
	 * @return the focused module when the templates are executed
	 */
	public String getFocusedModule() {
		return focusedModule;
	}

	/**
	 * 
	 * @return the web package to use.
	 */
	public JavaPackage getWebPackage() {
		return webPackage;
	}

	/**
	 * 
	 * @return the web package to use.
	 */
	public JavaPackage getDomainPackage() {
		return domainPackage;
	}

	public IJavaTemplate[] getTemplates() {
		return templates;
	}

}
